package indi.bamboo.generate;

import com.lowagie.text.Font;
import com.lowagie.text.*;
import com.lowagie.text.rtf.RtfWriter2;
import indi.bamboo.generate.mapper.PostgreTableMapper;
import indi.bamboo.generate.mapper.TableMapper;
import indi.bamboo.generate.model.enums.DatabaseEnum;
import indi.bamboo.generate.util.WordUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @ClassName GenerateMain
 * @Description 自动生成Word文件的数据库设计文档
 * @Author Bamboo
 * @date 2018/11/8 下午 3:06
 * @Version 1.0
 */
public class GenerateMain {

    /**
     * @param args args
     * @Description 执行方法
     * @author Bamboo aspbamboo@gmail.com
     * @date 2018/11/08 15:07:25
     */
    public static void main(String[] args) {
        String ip = "172.17.17.39";
        String port = "5432";
        String databaseName = "vjsp_digit";
        String username = "postgres";
        String password = "";

        String url = ip + ":" + port + "/" + databaseName;
        // 创建Word文档
        SqlSession session = getMapper(url, username, password, DatabaseEnum.POSTGRE);
        createWord(session.getMapper(PostgreTableMapper.class), databaseName);
    }

    /**
     * 生成Word文件的数据库设计文档
     *
     * @param tableMapper  获取数据库表信息接口对象
     * @param databaseName 数据库名称
     * @author Bamboo aspbamboo@gmail.com
     * @date 2018/11/08 16:52:59
     */
    private static void createWord(TableMapper tableMapper, String databaseName) {
        // 创建文件
        File file = new File("\\数据库设计文档.docx");
        if (!file.getParentFile().exists()) {
            boolean result = file.getParentFile().mkdirs();
            if (result) {
                System.out.println("文件创建失败");
            }
        }

        // 获取所有表名及其说明
        List<Map<String, Object>> tableList = tableMapper.selectAllTable(databaseName);

        // 创建word文档,并设置纸张的大小
        Document document = new Document(PageSize.A4);

        try {
            // 创建word文档
            RtfWriter2.getInstance(document, new FileOutputStream(file));
            document.open();
            // 设置文档标题
            Paragraph title = new Paragraph("数据库表设计文档", new Font(Font.NORMAL, 24, Font.BOLDITALIC, new Color(0, 0, 0)));
            // 设置对齐
            title.setAlignment(1);
            document.add(title);

            // 通过查询出来的表遍历, 生成表格
            for (Map<String, Object> stringObjectMap : tableList) {
                // 表名
                String tableName = (String) stringObjectMap.get("name");

                // 表说明
                String comment = (String) stringObjectMap.get("comment");

                // 标题2:表名及其说明
                Paragraph title2 = new Paragraph("表名：" + tableName + " " + StringUtils.defaultString(comment, "") + "");
                title2.setFont(new Font(Font.NORMAL, 13, Font.BOLD));

                // 创建有6列的表格
                Table table = new Table(6);
                document.add(new Paragraph(""));
                // 设置表格边框宽度
                table.setBorderWidth(1);
                // 设置表格边框颜色
                table.setBorderColor(Color.BLACK);
                // 设置表格边框填充
                table.setPadding(0);
                // 设置表格间距
                table.setSpacing(0);

                // 设置表格标题
                String[] tableTitle = new String[]{"字段名", "类型", "允许为空", "默认值", "主键", "字段说明"};
                int[] widthArr = new int[]{3, 3, 2, 2, 1, 6};
                table.setWidths(widthArr);
                table.setWidth(100);
                WordUtil.createTableTitle(table, tableTitle, null, new Color(176, 196, 222), 1, 1);

                // 设置表格内容
                editTable(table, tableMapper, tableName);
                // 写入表说明
                document.add(title2);
                // 写入表格
                document.add(table);
            }
            System.out.println("文件生成成功，位置在项目根盘符");
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            document.close();
        }
    }

    /**
     * 编辑表格，设置表格内容
     *
     * @param table       Word表格
     * @param tableMapper 查询接口类
     * @param tableName   数据库表名
     * @author Bamboo aspbamboo@gmail.com
     * @date 2018/11/09 11:12:17
     */
    private static void editTable(Table table, TableMapper tableMapper, String tableName) {
        // 获取某张表的所有字段说明
        List<Map<String, String>> fieldList = tableMapper.selectFields(tableName);

        // 字段数
        for (Map<String, String> map : fieldList) {
            try {
                // 字段名
                table.addCell(Optional.ofNullable(map.get("NAME")).orElse(map.get("name")));
                // 类型
                table.addCell(Optional.ofNullable(map.get("DATA_TYPE")).orElse(map.get("data_type")));
                // 允许为空
                table.addCell(String.valueOf(Optional.ofNullable(map.get("NULLABLE")).orElse(map.get("nullable"))));
                // 默认值
                table.addCell(Optional.ofNullable(map.get("DEFAULT_VALUE")).orElse(map.get("default_value")));
                // 主键
                table.addCell(String.valueOf(Optional.ofNullable(map.get("COLUMN_KEY")).orElse(map.get("column_key"))));
                // 字段说明
                table.addCell(Optional.ofNullable(map.get("COMMENT")).orElse(map.get("comment")));
            } catch (BadElementException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取查询表相关信息用的Mapper
     *
     * @param url      链接地址
     * @param username 用户名
     * @param password 密码
     * @param database 数据库
     * @return indi.bamboo.generate.mapper.MysqlTableMapper
     * @author Bamboo aspbamboo@gmail.com
     * @date 2022/08/18 22:22:25
     */
    private static SqlSession getMapper(String url, String username, String password, DatabaseEnum database) {
        // 1、 通过Java API构建SqlSessionFactory
        // 1.1 数据源
        PooledDataSource dataSource = new PooledDataSource();
        dataSource.setDriver(database.getDriverClass());
        dataSource.setUrl(database.getUrlPrefix() + url + database.getUrlSuffix());
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        // 1.2 事务管理器
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("dev", transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);

        // 1.3 注册映射器类所在包名下的所有映射器
        configuration.addMappers("indi.bamboo.generate.mapper");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
        return sqlSessionFactory.openSession();
    }
}
